// estruturas.h

#include <stdio.h>		/* for printf() */
#include <sys/ipc.h>		/* for shmget(),shmat(), and shmctl() */
#include <sys/shm.h>		/* for shmget(),shmat(), and shmctl() */
#include <sys/sem.h>	        /* for semget(), semop(), semctl() */
#include <stdlib.h>


 #define MSG_EST
/*
 * Constantes Necess�rias 
 */
#define MEM_TAA		0x1234
#define MEM_PCB		0x2345
#define MEM_SUPERBLOCO	0x3456
#define MEM_BUFFER 	0x4321

#define SEM_SUPER_KEY	0x5555
#define SEM_TAA_KEY	0x1235

#define TAM_BUFFER_SO 	1024
#define TAM_BLOCO 	1024


typedef struct{
	long int numero_cluster;
	int tipo_operacao;
	long int pid;
	long int numero_bytes;
	long int endereco;
} Requisicao_cid;


//Estrutura do Inode
typedef struct{
	int tipo;				//0 = diretorio, 1 = arquivo
	int idi_node;
	int idproprietario;
	int idgrupo;
	unsigned short bits_protecao;		//9 bits usados apenas: 3 pra user, 3 pra group, 3 pra other. Sao tres pois definem
	
	long int criacao;
	long int ultima_modificacao;
	long int ultimo_acesso;
	long int tamanho;
	long int direto[10];
	long int single;
	long int doubles;
	long int triple;
	char dispositivo[100];	
}Inode;

//Estrutura do Superbloco
typedef struct{
	Inode lista_inodes;
	long int clusters_livres[184];   //Lista de intervalos
	long int clusters_danificados[50];
}Superbloco;



typedef struct lista_aa  {
	int idi_node;
	Inode i_node;
	int quant_proc_acessando;
	//int permissoes;
	struct lista_aa * prox;
}No_taa;


typedef struct {
		int aberto;		//Bit de validade
		No_taa *laa_ptr;	//Ponteiro para a entrada correspondente na lista de arquivos abertos
		int buffer;		//buffer de arquivo
		int modo_abertura;		//Modo de abertura
		unsigned long ponteiro_arq;	//Ponteiro de arquivo
		//cluster na cache de blocos	    //NECESSARIO?
		//cache de blocos		    //NECESSARIO?
		//int precisa_gravar_chache_blocos; //NECESSARIO?		
} Descritor;	


//Estrutura do PCB
typedef struct{
	long int pid;
	int inode_corrente;
	Descritor vetor_descritores[20];
}Pcb;


struct sembuf	g_lock_sembuf[1];
struct sembuf	g_unlock_sembuf[1];

int g_sem_taa_id;
int g_sem_super_id;

static int key_taa;
static int key_buffer;

int mem_pcb_id;
char *mem_pcb_addr;

int mem_taa_id;
char *mem_taa_addr;

int mem_superbloco_id;
char *mem_superbloco_addr;

int mem_buffer_id;
char *mem_buffer_addr;

int mem_cluster_linode_id;
char *mem_cluster_linode_addr;

int mem_cluster_sfd_id;
char *mem_cluster_sfd_addr;


Inode inode_aux;
Descritor descritor_aux;

int long clusters_double[2048];
int long clusters_single[2048];
int long clusters_triple[2048];

char *buffer_so;


void init();

void init()
{
	int i;

/*************************************************************************************************************/
// Memorias compartilhadas
	/*
	 * Criando a memoria compartilhada PCB
	 */
	mem_pcb_id = shmget( MEM_PCB, sizeof(Pcb), IPC_CREAT | 0666);
	mem_pcb_addr = shmat(mem_pcb_id, NULL, 0);

	#ifdef MSG_EST
	printf("Criando memoria compartilhada PCB...\n");
	#endif	

	/*
	 * Criando o primeiro noh da memoria compartilhada TAA
	 */
	mem_taa_id = shmget( MEM_TAA, sizeof(No_taa), IPC_CREAT | 0666);
	mem_taa_addr = shmat(mem_taa_id, NULL, 0);

	No_taa *taa;
	taa = (No_taa *) mem_taa_addr;
	// inicializa TAA

	// coloca NULLcomo chave do proximo
	taa->prox = NULL;
	
	#ifdef MSG_EST
	printf("Criando memoria compartilhada TAA...\n");
	#endif	

	/*
	 * Criando a memoria compartilhada SuperBloco
	 */
	mem_superbloco_id = shmget( MEM_SUPERBLOCO, sizeof(Superbloco), IPC_CREAT | 0666);
	mem_superbloco_addr = shmat(mem_superbloco_id, NULL, 0);
	
	#ifdef MSG_EST
	printf("Criando memoria compartilhada SuperBloco...\n");
	#endif	
	
		
	 //* Criando a memoria compartilhada Buffer_SO
	 
	mem_buffer_id = shmget( MEM_BUFFER, sizeof(char*), IPC_CREAT | 0666);
	mem_buffer_addr = shmat(mem_buffer_id, NULL, 0);

	#ifdef MSG_EST
	printf("Criando memoria compartilhada Buffer SO...\n");
	#endif	
/*************************************************************************************************************/
// Semaforos
	
	/*
	 * Construindo a estrutura de controle do semaforo
	 */
	g_lock_sembuf[0].sem_num   =  0;
	g_lock_sembuf[0].sem_op    = -1;
	g_lock_sembuf[0].sem_flg   =  0;
	g_unlock_sembuf[0].sem_num =  0;
	g_unlock_sembuf[0].sem_op  =  1;
	g_unlock_sembuf[0].sem_flg =  0;

	/*
	 * Criando o semaforo para proteger a TAA
	 */	
	g_sem_taa_id = semget( SEM_TAA_KEY, 1, IPC_CREAT | 0666 );
	semop( g_sem_taa_id, g_unlock_sembuf, 1 );

	#ifdef MSG_EST
	printf("Criando semaforo para proteger a TAA...\n");
	#endif	

	/*
	 * Criando o semaforo para proteger o Superbloco
	 */	
	g_sem_super_id = semget( SEM_SUPER_KEY, 1, IPC_CREAT | 0666 );
	semop( g_sem_super_id, g_unlock_sembuf, 1 );

	#ifdef MSG_EST
	printf("Criando semaforo para proteger o SuperBloco...\n");
	#endif	



	key_taa = MEM_TAA;
	key_buffer = MEM_BUFFER;
}

void remover_shm()
{
 	/* 
	* Remove a memoria compartilhda do PCB
        */
   	shmctl(mem_pcb_id ,IPC_RMID,NULL);

	/* 
	* Remove a memoria compartilhda do Superbloco
        */
   	shmctl(mem_superbloco_id ,IPC_RMID,NULL);

	/* 
	* Remove a memoria compartilhda da Tabela de Arquivos Abertos
        */
   	shmctl(mem_taa_id ,IPC_RMID,NULL);

	/*
        * Removendo o semaforo do Superbloco
        */
        semctl( g_sem_super_id, 0, IPC_RMID, 0);

	/*
        * Removendo o semaforo da Tabela de Arquivos Abertos
        */
        semctl( g_sem_taa_id, 0, IPC_RMID, 0);

	/* 
	* Remove a memoria compartilhda do Buffer SO
        */
   	shmctl(mem_buffer_id ,IPC_RMID,NULL);

}
